<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.global.js"></script>
</head>

<body>
    <div id="app">
        <p ref="p">{{a}}</p>
        <p>
            <button @click="addA">a++</button>
        </p>
    </div>
</body>
<script>
    // Vue3  => Vue的第三个大版本修改  
    // 相较于Vue2  
    // 1. 选项式语法做了修改  



    // Vue3
    // 1. Vue  => 全局对象  => {createApp,nextTick,ref,reactive}
    // 2. Vue中对象存有创建引用的方法  var {createApp} = Vue;
    // 3. Vue3的选项式语法中 没有el属性 => 通过app.mount() 指定挂载的元素
    // 4. Vue3的选项式语法中 data是一个返回对象的函数  => 所有的组件均是如此 
    // 5. Vue3中 data methods computed 不在存储在Vue组件(实例)上  => 而是单独存储到一个对象上(代理对象 proxy)  =>  方法中的this默认都指向代理对象  => 取值和赋值都通过代理对象执行
    // 6. Vue3中 全局属性 组件 指令 插件 都是依赖于app定义的

    // 组合式语法

    console.log(Vue);

    var { createApp, nextTick } = Vue;
    var { ref, reactive, readonly, computed,watch } = Vue;
    var app = createApp({
        // 组合式
        setup: function (props) {
            console.log("setup钩子函数开始执行");

            // watch 数据监听 
            // 侦听一个或多个响应式数据源，并在数据源变化时调用所给的回调函数。

            // watch(source,callback,options)
            // source => 监听的数据源
            // callback => 数据发生改变执行的回调函数
            // options  => 监听时的相关配置
            //       deep:true    深度监听(主要针对ref对象中value值也是一个对象情况)
            //       immediate:true,  watch监听默认是惰性的, 设置immediate:true可以让其在初始化阶段立即执行一次  => newValue是初始值 oldValue => undefined
            //       flush:"sync/pre(默认)/post"
            //               sync  => 数据改变之后立即执行
            //               pre  => 数据改变后, 视图更新前执行
            //               post => 数据改变且视图更新后执行

            // 默认情况下 => 数据发生改变,视图不会立即更新 => 此时DOM中的内容还是原本的内容

            // 1. 通过ref属性获取元素/组件    => Vue3组合式语法中如何对于ref名获取元素?
            //      a. 先给元素/组件绑定ref名
            //      b. 对于ref名声明变量,设置ref()
            //      c. setup返回值中返回对于的变量名
            
            // 2. 如何获取视图更新后的内容

            var a = ref(10); // {value:10}
            var p = ref();

            //  数据发生改变,视图不会立即更新  => 此时DOM中的内容还是原本的内容
            // watch(a,function(newVal,oldVal){
            //     console.log("数据a发生改变", newVal,oldVal);
            //     console.log("p",p.value.innerHTML);
            // },{flush:"pre"})

            // 何获取视图更新后的内容
            // watch(a,function(newVal,oldVal){
            //     setTimeout(()=>{
            //         console.log("数据a发生改变", newVal,oldVal);
            //         console.log("p",p.value.innerHTML);
            //     },0)
            // })

            // watch(a,function(newVal,oldVal){
            //     nextTick(()=>{
            //         console.log("数据a发生改变", newVal,oldVal);
            //         console.log("p",p.value.innerHTML);
            //     })
            // })
            // watch(a,function(newVal,oldVal){
            //     console.log("数据a发生改变", newVal,oldVal);
            //     console.log("p",p.value.innerHTML);
            // },{flush:"post"}) // vue新增

            // 对比 sync pre  post

            watch(a,function(newVal,oldVal){
                console.log("数据a发生改变:sync");
            },{flush:"sync"})
            watch(a,function(newVal,oldVal){
                console.log("数据a发生改变:pre");
            },{flush:"pre"})
            watch(a,function(newVal,oldVal){
                console.log("数据a发生改变:post");
            },{flush:"post"})



            // 定义方法 methods
            function addA() {
                a.value++;
            }




            // 闭包  => setup函数中返回的数据/计算属性/方法/监听  就是后面选项式语法中接收的
            // 对象中的键名 => 后面选项式语法中proxy代理对象中的属性名
            // 对象中的键值 => setup函数中的对象 方法
            return {
                a: a, // a:ref对象
                p: p,
                addA: addA,
            }
        },
        // 选项式
        // data(){},
        // computed:{},
        // methods:{},
        // watch:{},

        beforeCreate() {
            console.log("beforeCreate", this);
            // console.log("beforeCreate",this.a);  // proxy对象取值是进行了解包  this.a => ref.value;

            // this.a = 100;   // ref.value = 100;
            // console.log("beforeCreate",this.a); // this.a => ref.value;

        },

        created() {
            console.log("created", this);
        },
        // mounted() {
        //     console.log("组件挂载完毕",this);
        // },
    })

    console.log("app", app);
    app.mount("#app");




</script>



</html>